const mongoClient = require('mongodb').MongoClient;
const url = 'mongodb://localhost:27017/';//数据库连接
const dbase = 'helloword';//数据库名
const prefix = 'db_';//数据库前缀
let currentTable = null;

module.exports = async function () {
    let currentTable = null;//当前数据集合

    /**
     * 聚合函数
     * @param type 聚合的表达式名  sum 求和，avg 平均值，min最小值，max最大值 [必填]
     * @param field 进行聚合的字段名 [必填]
     * @param groupBy 分类聚合字段，默认为null
     * @returns {返回对应聚合值}
     */
    async function aggregate(type, field, groupBy = null) {
        if (!currentTable || !field) return false;
        var option = {_id: groupBy};
        option.value = JSON.parse('{"$' + type + '":"$' + field + '"}')

        return new Promise(function (resolve) {
            currentTable.aggregate({$group: option}, function (err, res) {
                err ? resolve(err) : res.toArray(function (err2, res2) {
                    err2 ? resolve(err2) : resolve(res2[0].value);
                });
            })
        })
    }

    return new Promise(function (resolve, reject) {
        mongoClient.connect(url, function (err, mongodbConnect) {
            if (err) throw err;
            let db = mongodbConnect.db(dbase);//选择数据库
            console.log('连接成功');

            //数据库操作对象
            let mongodbObj = {
                prefix: prefix,//集合名前缀

                /**
                 * 插入文档
                 * @param data [Object] 插入的文档对象或数组
                 * @returns 当前插入的文档对象或文档数组
                 */
                insert: async function (data) {
                    if (!currentTable) return false;
                    return new Promise(function (resolve2) {
                        if (Object.prototype.toString.call(data) == '[object Object]') {
                            data = [data];
                        }
                        currentTable.insertMany(data, function (err, res) {
                            if (err) resolve2(false);
                            resolve2(res.ops.length < 2 ? res.ops[0] : res.ops);
                        });
                    });
                },

                /**
                 * 单条查询
                 * @param condition 查询条件，与mongodb查询对象一致
                 * @returns 返回单条文档对象，若没有查询结果返回false
                 */
                get: async function (condition) {
                    if (!currentTable) return false;
                    if (!condition) condition = {};
                    return new Promise(function (resolve2) {
                        currentTable.findOne(condition, function (err, res) {
                            if (err) resolve2(err);
                            resolve2(res?res:false);
                        });
                    });
                },

                /**
                 * 多条查询
                 * @param condition 查询条件，与mongodb查询对象一致
                 * @param options={
                 *        limit:每次查询返回结果最大数
                 *        sort:排序规则 规则mongodb一致
                 *        pages:从第几页开始返回数据
                 *        field:返回字段，json对象 {字段名：true/false} true为返回 false为不返回
                 * }
                 * @returns 返回文档对象数组，若没有查询结果返回false
                 */
                find: async function (condition, options = {}) {
                    if (!currentTable) return false;
                    if (!condition) condition = {};
                    if (!options.limit) options.limit = 0;
                    if (!options.sort) options.sort = "";
                    if (!options.pages) options.pages = 1;
                    if (!options.field) options.field = "";

                    return new Promise(function (resolve2) {
                        currentTable.find(condition,{fields:options.field}).sort(options.sort)
                            .skip((options.pages - 1) * options.limit)
                            .limit(options.limit)
                            .toArray(function (err, res) {
                                if (err) resolve2(err);
                                resolve2(res.length==0?false:res);
                            });
                    });
                },

                /**
                 * 最小值
                 * field 进行聚合的字段名 [必填]
                 * groupBy 分类聚合字段，默认为null
                 * @returns 最小值
                 */
                min: async function (field, groupBy) {
                    return await aggregate('min', field, groupBy);
                },

                /**
                 * 最大值
                 * field 进行聚合的字段名 [必填]
                 * groupBy 分类聚合字段，默认为null
                 * @returns 最大值
                 */
                
                max: async function (field, groupBy) {
                    return await aggregate('max', field, groupBy);
                },

                /**
                 * 平均值
                 * field 进行聚合的字段名 [必填]
                 * groupBy 分类聚合字段，默认为null
                 * @returns 平均值
                 */
                avg: async function (field, groupBy) {
                    return await aggregate('avg', field, groupBy);
                },

                /**
                 * 求和
                 * field 进行聚合的字段名 [必填]
                 * groupBy 分类聚合字段，默认为null
                 * @returns 求和
                 */
                sum: async function (field, groupBy) {
                    return await aggregate('sum', field, groupBy);
                },


                /**
                 * 更新
                 * @param condition 查询条件，与mongodb查询对象一致
                 * @param data 更新的数据 json对象
                 * @param isBatch 是否批量更新
                 * @returns {Promise<*>}
                 */
                update: async function (condition, data, isBatch=false) {
                    if (!currentTable) return false;
                    if (!condition) condition = {};
                    return new Promise(function (resolve2) {
                        if (!isBatch) {
                            currentTable.updateOne(condition, {$set:data}, function (err, res) {
                                if (err) resolve2(false);
                                resolve2(true);
                            });
                        } else {
                            currentTable.updateMany(condition,  {$set:data}, function (err, res) {
                                if (err) resolve2(false);
                                resolve2(true);
                            });
                        }
                    });
                },

                //删除
                del: async function (condition, isBatch) {
                    if (!currentTable) return false;
                    if (!condition) condition = {};
                    return new Promise(function (resolve2) {
                        if (!isBatch) {
                            currentTable.deleteOne(condition, function (err, res) {
                                if (err) resolve2(false);
                                resolve2(true);
                            });
                        } else {
                            currentTable.deleteMany(condition, function (err, res) {
                                if (err) resolve2(false);
                                resolve2(true);
                            });
                        }
                    });
                }
            };
            //创建集合
            db.createTable = async function (tableName) {
                return new Promise(function (resolve2) {
                    db.createCollection(mongodbObj.prefix + tableName, function (err2, res) {
                        if (err2) resolve2(err2); else resolve2(true);
                    });
                })
            },
            resolve({
                dbOperate: new Proxy({}, {
                    get: function (target, key) {//操作对象
                        //if (key && key.substr(0, mongodbObj.prefix.length) == mongodbObj.prefix) {
                        if (key) {
                            currentTable = db.collection(mongodbObj.prefix+key);
                            return mongodbObj;
                        } else {
                            return null;
                        }
                    }
                }),
                mongodb: db//数据库连接
            });
        });
    });
}

